<html>

<head>
    <title>WebGL Beginner's Guide - Chapter 2 - Cone example</title>
    <meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>

    <!-- CSS Styles //-->
    <link href='css/style.css' type='text/css' rel='stylesheet'>
    <link href='css/desert.css' type='text/css' rel='stylesheet' />
    <link href='css/smoothness/jquery-ui-1.8.13.custom.css' type='text/css' rel='stylesheet' />

    <!-- JavaScript Libraries //-->
    <script type='text/javascript' src='js/gl-matrix-min.js'></script>
    <script type='text/javascript' src='js/jquery-1.5.1.min.js'></script>
    <script type='text/javascript' src='js/jquery-ui-1.8.13.custom.min.js'></script>
    <script type='text/javascript' src='js/prettify.js'></script>
    <script type='text/javascript' src='js/utils.js'></script>
    <script type='text/javascript' src='js/codeview.js'></script>

    <!-- Fragment Shader //-->
    <script id='shader-fs' type='x-shader/x-fragment'>
    #ifdef GL_ES
    precision highp float;
    #endif

    void main(void) {
        gl_FragColor = vec4(0.5, 0.9, 0.2, 1.0); //Green
    }
</script>

    <!-- Vertex Shader //-->
    <script id='shader-vs' type='x-shader/x-vertex'>
    attribute vec3 aVertexPosition;

    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;

    void main(void) {
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        gl_PointSize = 3.0;
    }
</script>

    <script id='code-js' type='text/javascript'>
        var gl = null; // WebGL context
        var prg = null; // The program (shaders)
        var c_width = 0; // Variable to store the width of the canvas
        var c_height = 0; // Variable to store the height of the canvas

        var coneVertexBuffer = null; //The vertex buffer for the cone
        var coneIndexBuffer = null; // The index buffer for the cone

        var indices = [];
        var vertices = [];

        var mvMatrix = mat4.create(); // The Model-View matrix
        var pMatrix = mat4.create(); // The projection matrix

        /**
        * The program contains a series of instructions that tell the Graphic Processing Unit (GPU)
        * what to do with every vertex and fragment that we pass it. (more about this on chapter 3)
        * The vertex shader and the fragment shader together are called the program.
        */
        function initProgram() {
            var fgShader = utils.getShader(gl, 'shader-fs');
            var vxShader = utils.getShader(gl, 'shader-vs');

            prg = gl.createProgram();
            gl.attachShader(prg, vxShader);
            gl.attachShader(prg, fgShader);
            gl.linkProgram(prg);

            if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
                alert('Could not initialise shaders');
            }

            gl.useProgram(prg);

            prg.vertexPositionAttribute = gl.getAttribLocation(prg, 'aVertexPosition');
            prg.pMatrixUniform = gl.getUniformLocation(prg, 'uPMatrix');
            prg.mvMatrixUniform = gl.getUniformLocation(prg, 'uMVMatrix');
        }

        /**
        * Creates the buffers that contain the geometry of the cone
        */
        function initBuffers() {

            vertices = [1.5, 0, 0,
                -1.5, 1, 0,
                -1.5, 0.809017, 0.587785,
                -1.5, 0.309017, 0.951057,
                -1.5, -0.309017, 0.951057,
                -1.5, -0.809017, 0.587785,
                -1.5, -1, 0,
                -1.5, -0.809017, -0.587785,
                -1.5, -0.309017, -0.951057,
                -1.5, 0.309017, -0.951057,
                -1.5, 0.809017, -0.587785];

            indices = [0, 1, 2,
                0, 2, 3,
                0, 3, 4,
                0, 4, 5,
                0, 5, 6,
                0, 6, 7,
                0, 7, 8,
                0, 8, 9,
                0, 9, 10,
                0, 10, 1];

            //The following code snippet creates a vertex buffer and binds data to it
            coneVertexBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, coneVertexBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);


            coneIndexBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, coneIndexBuffer);
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
            gl.bindBuffer(gl.ARRAY_BUFFER, null);

        }

        /**
        * Draws the scene
        */
        function drawScene() {

            gl.clearColor(0.0, 0.0, 0.0, 1.0);
            gl.enable(gl.DEPTH_TEST);

            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
            gl.viewport(0, 0, c_width, c_height);

            mat4.perspective(45, c_width / c_height, 0.1, 10000.0, pMatrix);
            mat4.identity(mvMatrix);
            mat4.translate(mvMatrix, [0.0, 0.0, -5.0]);

            gl.uniformMatrix4fv(prg.pMatrixUniform, false, pMatrix);
            gl.uniformMatrix4fv(prg.mvMatrixUniform, false, mvMatrix);

            gl.bindBuffer(gl.ARRAY_BUFFER, coneVertexBuffer);
            gl.vertexAttribPointer(prg.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(prg.vertexPositionAttribute);

            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, coneIndexBuffer);
            gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
        }

        /**
        * Render Loop
        */
        function renderLoop() {
            requestAnimFrame(renderLoop);
            drawScene();
        }

        /**
        * Executes the WebGL application
        * This function is invoked on the onLoad event of the web page. 
        */
        function runWebGLApp() {
            //Obtains a WebGL context
            gl = utils.getGLContext('canvas-element-id');
            //Initializes the program (shaders). More about this on chapter 3!
            initProgram();
            //Initializes the buffers that we are going to use to draw the cone (vertex buffer and index buffer)
            initBuffers();
            //Renders the scene!
            renderLoop();
        }
    </script>
</head>


<body onLoad='runWebGLApp()'>
    <div id='top'>
        <h1>WebGL Beginner's Guide - Chapter 2</h1>
        <h2>Rendering a Cone</h2>
        <div id='logo-packt'><img src='packt.gif' /></div>
        <p>This example shows how to render a cone in WebGL. (functions initBuffers and drawScene).</p>
    </div>

    <div id='contents'>
        <div id='canvasContainer'>
            <canvas id='canvas-element-id' width='480' height='400'>
                Your browser does not support the HTML5 canvas element.
            </canvas>
        </div>
    </div>

    <div id='bottom'>
    </div>
    <script>cview.run();</script>
</body>

</html>